<?php

/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

class AutoRouterImpl implements IRouter
{

  /**
   *
   * @var array
   */
  protected $parsed = array();

  /**
   *
   * @var ICache
   */
  protected $cache;

  /**
   *
   * @var string
   */
  protected $cacheid = 'router';

  public function initialize()
  {
  }

  /**
   *
   * @return ICache
   */
  protected function getCache()
  {
    static $cache;

    if (empty($cache)) {
      $cache = new YAMLFileCache(Simplify::getConfig()->get('cache:dir'));

      if ($cache->cached($this->cacheid)) {
        $this->cache = $cache->read($this->cacheid);

        if (! is_array($this->cache)) {
          $this->cache = array();
        }
      }
    }

    if (Dictionary::parseFrom(Simplify::getRequest()->get('get'))->has('CLEAR_AUTO_ROUTER_CACHE')) {
      $cache->write($this->cacheid, array());
      $this->cache = array();
    }

    return $cache;
  }

  protected function cache($route, $data)
  {
    $cache = $this->getCache();
    $this->cache[$route] = $data;
    $cache->write($this->cacheid, $this->cache);
  }

  public function build($route, $params)
  {
  }

  public function parse($route)
  {
    $this->getCache();

    if (! isset($this->cache[$route])) {
      try {
        $base = Simplify::getConfig()->get('home_dir');
        $data = $this->find($route, $base);
        $this->cache($route, $data);
      }
      catch (RouterException $e) {
        $base = Simplify::getConfig()->get('sy_dir') . '/app/home';
        $data = $this->find($route, $base);
      }

      $data = Dictionary::parseFrom($data);
    }
    else {
      $data = Dictionary::parseFrom($this->cache[$route]);

      $file = $data->get('path') . $data->get('controller') . '_controller.php';

      if (! file_exists($file)) {
        throw new RouterException("Controller file not found: <b>$file</b>");
      }

      require_once ($file);
    }

    return $data;
  }

  protected function find($route, $base)
  {
    $words = preg_split('#/#', $route, - 1, PREG_SPLIT_NO_EMPTY);

    /**
     *
     * find path
     *
     */

    $path = '/';

    $dir = Simplify::getConfig()->get('home_controller', 'home');

    $find = array(
      '-', ' '
    );

    while (count($words) && is_dir($base . $path . str_replace($find, '_', $words[0]))) {
      $dir = str_replace($find, '_', $words[0]);
      $path .= str_replace($find, '_', array_shift($words)) . '/';
    }

    /**
     *
     * find controller
     *
     */

    if (count($words)) {
      $file = $base . $path . str_replace(array(
        '-', ' '
      ), '_', $words[0]) . '_controller.php';

      if (file_exists($file)) {
        $controller = str_replace(array(
          '-', ' '
        ), '_', array_shift($words));
      }
    }

    if (empty($controller)) {
      $file = $base . $path . $dir . '_controller.php';

      if (! file_exists($file)) {
        throw new RouterException("Controller file not found: <b>$file</b>");
      }

      $controller = $dir;
    }

    require_once ($file);

    $class = Inflector::classify($controller . '_controller');

    if (! class_exists($class)) {
      throw new RouterException("Controller class not found: <b>$class</b>");
    }

    /**
     *
     * find action
     *
     */

    if (count($words) && method_exists($class, 'action_' . str_replace(array(
      '-', ' '
    ), '_', $words[0]))) {
      $action = str_replace(array(
        '-', ' '
      ), '_', array_shift($words));
    }
    else {
      $action = 'index';
    }

    /**
     *
     * find parameters
     *
     */

    $params = count($words) ? $words : array();

    /**
     *
     * pack data
     *
     */

    $data = array(
      'path' => $base . $path, 'controller' => $controller, 'action' => $action, 'params' => $params
    );

    return $data;
  }

}

?>